#if (FEATURE_MODE == 0)


#include "ctc_error.h"
#include "ctc_diag.h"
#include "sys_usw_common.h"
#include "sys_usw_mchip.h"
#include "sys_usw_register.h"
#include "sys_usw_port.h"
#include "sys_usw_linkagg.h"
#include "sys_usw_diag.h"
#include "sys_usw_lb_hash.h"

#include "drv_api.h"

extern int32
sys_usw_nh_ecmp_get_lb_hash_mem_api(uint8 lchip, uint32 ecmp_nh_id, uint16 hash_value, uint32 * p_nh_id);

/*lb hash algorithm define enum and struct*/
#define SYS_DIAG_LB_HASH_DATA_LEN 32
#define SYS_DIAG_LB_HASH_SEL_ID_NUM 8
#define SYS_DIAG_LB_HASH_SEL_EXT_NUM 4
#define SYS_DIAG_LB_HASH_GEN_HASH_NUM 10
#define SYS_DIAG_LB_HASH_GEN_HASH_NUM_MERGE 4

#define SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, key_type, init_value, value) \
{ \
    uint32 field_idx = 0;\
    _sys_tsingma_diag_get_lb_hash_field(lchip, p_field_list, field_cnt, key_type, &field_idx); \
    value = (field_idx == CTC_MAX_UINT32_VALUE)?init_value:p_field_list[field_idx].data; \
}

#define SYS_DIAG_GET_LB_HASH_FIELD_EXT(lchip, p_field_list, field_cnt, key_type, value, val_len) \
{ \
    uint32 field_idx = 0;\
    _sys_tsingma_diag_get_lb_hash_field(lchip, p_field_list, field_cnt, key_type, &field_idx); \
    if ((field_idx != CTC_MAX_UINT32_VALUE) && (NULL != p_field_list[field_idx].ext_data)) \
        sal_memcpy(value, p_field_list[field_idx].ext_data, val_len); \
}

enum sys_diag_hash_packet_type_e
{
    SYS_DIAG_HASH_PACKET_TYPE_IPV4_VXLAN = 2,
    SYS_DIAG_HASH_PACKET_TYPE_IPV4_GRE = 4,
    SYS_DIAG_HASH_PACKET_TYPE_IPV4_INNER_IPV4 = 5,
    SYS_DIAG_HASH_PACKET_TYPE_IPV4_INNER_IPV6 = 6,
    SYS_DIAG_HASH_PACKET_TYPE_IPV4_UDP = 7,
    SYS_DIAG_HASH_PACKET_TYPE_IPV6_VXLAN = 8,
    SYS_DIAG_HASH_PACKET_TYPE_IPV6_GRE = 10,
    SYS_DIAG_HASH_PACKET_TYPE_IPV6_INNER_IPV6 = 11,
    SYS_DIAG_HASH_PACKET_TYPE_IPV6_INNER_IPV4 = 12,
    SYS_DIAG_HASH_PACKET_TYPE_IPV6_UDP = 13,
    SYS_DIAG_HASH_PACKET_TYPE_IPV4 = 24,
    SYS_DIAG_HASH_PACKET_TYPE_IPV6 = 25,
    SYS_DIAG_HASH_PACKET_TYPE_BRIDGE = 28,
    SYS_DIAG_HASH_PACKET_TYPE_MAX
};
typedef enum sys_diag_hash_packet_type_e sys_diag_hash_packet_type_t;

enum sys_diag_hash_poly_type_e
{
    SYS_DIAG_HASH_POLY_TYPE_CRC8_POLY1 = 0,
    SYS_DIAG_HASH_POLY_TYPE_CRC8_POLY2,
    SYS_DIAG_HASH_POLY_TYPE_XOR8,
    SYS_DIAG_HASH_POLY_TYPE_CRC12_POLY1,
    SYS_DIAG_HASH_POLY_TYPE_CRC12_POLY2,
    SYS_DIAG_HASH_POLY_TYPE_XOR16,
    SYS_DIAG_HASH_POLY_TYPE_CRC16_POLY1,
    SYS_DIAG_HASH_POLY_TYPE_CRC16_POLY2,
    SYS_DIAG_HASH_POLY_TYPE_CRC16_POLY3,
    SYS_DIAG_HASH_POLY_TYPE_CRC16_POLY4,
    SYS_DIAG_HASH_POLY_TYPE_CRC10_POLY1,
    SYS_DIAG_HASH_POLY_TYPE_CRC10_POLY2,
    SYS_DIAG_HASH_POLY_TYPE_CRC10_POLY3,
    SYS_DIAG_HASH_POLY_TYPE_CRC10_POLY4,
    SYS_DIAG_HASH_POLY_TYPE_CRC8_POLY3,
    SYS_DIAG_HASH_POLY_TYPE_CRC8_POLY4,
    SYS_DIAG_HASH_POLY_TYPE_CRC20_POLY1,
    SYS_DIAG_HASH_POLY_TYPE_CRC16_BISYNC,
    SYS_DIAG_HASH_POLY_TYPE_CRC16_CCITT,
    SYS_DIAG_HASH_POLY_TYPE_CRC32_POLY1,
    SYS_DIAG_HASH_POLY_TYPE_CRC11_POLY1,
    SYS_DIAG_HASH_POLY_TYPE_CRC11_POLY2,
    SYS_DIAG_HASH_POLY_MAX_TYPE,
};
typedef enum sys_diag_hash_poly_type_e sys_diag_hash_poly_type_t;

enum sys_usw_diag_calculate_type_e
{
    SYS_DIAG_CALC_HASH_CRC = 0,
    SYS_DIAG_CALC_HASH_XOR  =1,
};

struct sys_usw_diag_hash_crc_s
{
    uint32 type;
    uint32 poly;
    uint32 poly_len;
};
typedef struct sys_usw_diag_hash_crc_s sys_usw_diag_hash_crc_t;

sys_usw_diag_hash_crc_t  flow_hash_poly[] =
{ 
        {SYS_DIAG_CALC_HASH_CRC, 0x00000087, 8},     /*CRC8_POLY1*/   //x8+x7+x2+x+1
        {SYS_DIAG_CALC_HASH_CRC, 0x000000c3, 8},     /*CRC8_POLY2*/ //x8+x7+x6+x+1
        {SYS_DIAG_CALC_HASH_XOR, 8,          0},     /*XOR8*/
        {SYS_DIAG_CALC_HASH_CRC, 0x00000053, 12},    /*CRC12_POLY1*/ //x12+x6+x4+x+1
        {SYS_DIAG_CALC_HASH_CRC, 0x00000069, 12},    /*CRC12_POLY2*/ //x12+x6+x5+x3+1
        {SYS_DIAG_CALC_HASH_XOR, 16,          0},    /*XOR16*/
        {SYS_DIAG_CALC_HASH_CRC, 0x0000002d, 16},    /*CRC16_POLY1*/ //x16+x5+x3+x2+1
        {SYS_DIAG_CALC_HASH_CRC, 0x00000039, 16},    /*CRC16_POLY2*/ // x16+x5+x4+x3+1
        {SYS_DIAG_CALC_HASH_CRC, 0x00000429, 16},    /*CRC16_POLY3*/ //x16+x10+x5+x3+1
        {SYS_DIAG_CALC_HASH_CRC, 0x00000215, 16},    /*CRC16_POLY4*/ //x16+x9+x4+x2+1
        {SYS_DIAG_CALC_HASH_CRC, 0x00000009, 10},    /*CRC10_POLY1*/ //x10+x3+1
        {SYS_DIAG_CALC_HASH_CRC, 0x0000001b, 10},    /*CRC10_POLY2*/ //x10+x4+x3+x+1
        {SYS_DIAG_CALC_HASH_CRC, 0x00000027, 10},    /*CRC10_POLY3*/ //x10+x5+x2+x+1
        {SYS_DIAG_CALC_HASH_CRC, 0x00000081, 10},    /*CRC10_POLY4*/ //x10+x7+1
        {SYS_DIAG_CALC_HASH_CRC, 0x0000001d, 8},     /*CRC8_POLY3*/ //x8+x4+x3+x2+1
        {SYS_DIAG_CALC_HASH_CRC, 0x0000002b, 8},     /*CRC8_POLY4*/ //x8+x5+x3+x+1
        {SYS_DIAG_CALC_HASH_CRC, 0x00000009, 20},    /*CRC20_POLY1*/ //x20+x3+1
        {SYS_DIAG_CALC_HASH_CRC, 0x00008005, 16},    /*CRC16_BISYNC*/ //x16+x15+x2+1
        {SYS_DIAG_CALC_HASH_CRC, 0x00001021, 16},    /*CRC16_CCITT*/ //x16+x12+x5+1
        {SYS_DIAG_CALC_HASH_CRC, 0x00000125, 32},    /*CRC32_poly1*/ //x32+x8+x5+x2+1
        {SYS_DIAG_CALC_HASH_CRC, 0x00000005, 11},    /*CRC11_POLY1*/ //x11+x2+1
        {SYS_DIAG_CALC_HASH_CRC, 0x00000017, 11},    /*CRC11_POLY2*/ //x11+x4+x2+x+1
};

struct sys_tsingma_diag_lb_hash_s
{
    uint32 src_gport;
    uint32 select_id : 8;
    uint32 is_vxlan  : 1;
    uint32 is_nvgre  : 1;
    uint32 rsv       : 22;

    uint16 hash_val1;
    uint16 hash_val2;
};
typedef struct sys_tsingma_diag_lb_hash_s sys_tsingma_diag_lb_hash_t;

STATIC uint32
_sys_usw_diag_hash_crc(uint32 seed, uint8 *data, uint32 bit_len, uint32 poly, uint32 poly_len)
{
    uint32 crc = 0;
    int32 i = 0;
    uint32 msb_bit = 0;
    uint32 poly_mask = 0;
    uint32 topone = 0;

    if (poly_len == 32)
    {
        poly_mask = 0xFFFFFFFF;
    }
    else
    {
        poly_mask = (1 << poly_len) - 1;
    }
    //poly_mask = (1 << poly_len) - 1;
    topone = (1 << (poly_len - 1));
    crc = seed & poly_mask;

    for (i = (bit_len - 1); i >= 0; i--) { // bits
        msb_bit = ((data[i/8] >> (i%8)) & 0x1) << (poly_len - 1);
        crc ^= msb_bit;
        crc = (crc << 1) ^ ((crc & topone) ? poly : 0);
    }

    crc &= poly_mask;
    return crc;
}

STATIC uint16
_sys_usw_diag_lb_hash_xor16(uint16* data, uint32 bit_len)
{
    uint32 i = 0;
    uint16 result = 0;
    uint16 len = bit_len/16;
    uint16 last_bits = bit_len%16;

    for (i = 0; i < len; i++)
    {
        result ^= data[i];
    }

    if (last_bits)
    {
        result ^= (data[len]&((1<<last_bits)-1));
    }

    return result;
}

STATIC uint8
_sys_usw_diag_lb_hash_xor8(uint8* data, uint32 bit_len)
{
    uint32 i = 0;
    uint16 result = 0;
    uint16 len = bit_len/8;
    uint16 last_bits = bit_len%8;

    for (i = 0; i < len; i++)
    {
        result ^= data[i];
    }

    if (last_bits)
    {
        result ^= (data[len]&((1<<last_bits)-1));
    }

    return result;
}

STATIC int32
_sys_usw_diag_gen_hash(uint8* p_data, uint32 data_len, uint8 hash_poly, uint8 merge_en, uint32* p_val)
{
    uint32 poly = 0;
    uint32 poly_len = 0;
    uint32 result = 0;
    uint8  seed = merge_en ? 0 : 0xFFFFFFFF; /*seed should be 0 for parallel hash calculate*/

    if (hash_poly == SYS_DIAG_HASH_POLY_TYPE_XOR8)
    {
        result = _sys_usw_diag_lb_hash_xor8((uint8*)p_data,data_len);
    }
    else if (hash_poly == SYS_DIAG_HASH_POLY_TYPE_XOR16)
    {
        result = _sys_usw_diag_lb_hash_xor16((uint16*)p_data,data_len);
    }
    else
    {
        poly = flow_hash_poly[hash_poly].poly;
        poly_len = flow_hash_poly[hash_poly].poly_len;
        result = _sys_usw_diag_hash_crc(seed, p_data, data_len, poly, poly_len);
    }
    *p_val = result;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_diag_crc_merge_hash(uint8 lchip, uint16 hash_value0, uint16 hash_value1, uint8 hash_poly)
{
    CrcHashMatrixCtl_m matrix_ctl;
    uint32 hash_matrix[8] = {0};
    uint32 cmd = 0;
    uint16 temp_val_a = 0;
    uint16 temp_val_b = 0;
    uint16 temp_val_c = 0;
    uint16 input_hash_value = 0;
    uint16 output_hash_value = 0;
    uint8  poly_len = 0;
    uint8  shift_bit = 0;
    uint8  block_num = 0;
    uint8  matrix_pos = 0;
    uint8  i = 0;
    uint8  j = 0;

    cmd = DRV_IOR(CrcHashMatrixCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &matrix_ctl));

    switch(hash_poly)
    {
        case SYS_LB_HASHPOLY_CRC16_POLY1:
            GetCrcHashMatrixCtl(A, gCrc8_field_f, &matrix_ctl, hash_matrix);
            poly_len = 8;
            shift_bit = 3;
            break;
        case SYS_LB_HASHPOLY_CRC16_POLY2:
            GetCrcHashMatrixCtl(A, gCrc16_field_f, &matrix_ctl, hash_matrix);
            poly_len = 16;
            shift_bit = 4;
            break;
        case SYS_LB_HASHPOLY_CRC16_POLY5:
            GetCrcHashMatrixCtl(A, gCrc16Bisync_field_f, &matrix_ctl, hash_matrix);
            poly_len = 16;
            shift_bit = 4;
            break;
        case SYS_LB_HASHPOLY_CRC16_POLY6:
            GetCrcHashMatrixCtl(A, gCrc16Ccitt_field_f, &matrix_ctl, hash_matrix);
            poly_len = 16;
            shift_bit = 4;
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }

    for (block_num=0; block_num<2; block_num++)
    {
        if (0 == block_num)
        {
            input_hash_value = hash_value0;
        }
        else
        {
            input_hash_value = hash_value1;
        }
        output_hash_value = input_hash_value ^ temp_val_a;

        for (i=0; i<poly_len; i++)
        {
            ((output_hash_value >> i) & 0x1) ? CTC_BIT_SET(temp_val_b, (i & 0xF)) : CTC_BIT_UNSET(temp_val_b, (i & 0xF));
        }

        for (i=0; i<poly_len; i++)
        {
            CTC_BIT_UNSET(temp_val_c, (i & 0xF));
            for (j=0; j<poly_len; j++)
            {
                matrix_pos = ((i & 0xF) << shift_bit) + (j & 0xF);
                ((CTC_IS_BIT_SET(temp_val_b, (j & 0xF))) & (CTC_IS_BIT_SET(hash_matrix[matrix_pos/8], (matrix_pos%8)))) ^ (CTC_IS_BIT_SET(temp_val_c, (i & 0xF))) 
                    ? CTC_BIT_SET(temp_val_c, (i & 0xF)) : CTC_BIT_UNSET(temp_val_c, (i & 0xF));
            }
        }

        temp_val_a = 0;
        for (i=0; i<poly_len; i++)
        {
            temp_val_a = (CTC_IS_BIT_SET(temp_val_c, (i & 0xF)) & (1 << (i & 0xF))) | temp_val_a;
        }
    }

    if (8 == poly_len)
    {
        output_hash_value = temp_val_b & 0xFF;
    }
    else if (16 == poly_len)
    {
        output_hash_value = temp_val_b;
    }

    return output_hash_value;
}

STATIC int32
_sys_tsingma_diag_get_lb_hash_field(uint8 lchip, ctc_field_key_t* p_field_list, uint32 field_cnt, uint32 field_type, uint32* p_out_field)
{
    uint32 field_id = 0;
    ctc_field_key_t* p_key_field = NULL;

    for (field_id=0; field_id<field_cnt; field_id++)
    {
        p_key_field = (ctc_field_key_t*)p_field_list + field_id;
        if (field_type == p_key_field->type)
        {
            *p_out_field = field_id;
            return CTC_E_NONE;
        }
    }
    if (field_id == field_cnt)
    {
        *p_out_field = CTC_MAX_UINT32_VALUE;
       return CTC_E_NOT_EXIST;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tsingma_diag_generate_lb_hash(uint8 lchip, ctc_field_key_t* p_field_list, uint32 field_cnt, uint8 mask_profile_id, sys_tsingma_diag_lb_hash_t* p_gen_lb_hash)
{
    uint8 ipv4_hash_en = 0;
    uint8 ipv6_hash_en = 0;
    /*uint8 mpls_hash_en = 0;*/
    uint8 gen_hash_key_valid= 0;
    uint8 idx = 0;
    uint8 step = 0;
    uint32 cmd = 0;
    ds_t ds;
    IpePreLookupCtl_m pre_lookup_ctl;
    uint8 layer3_type = 0;
    ipv6_addr_t   ipv6_sa = {0};
    ipv6_addr_t   ipv6_da = {0};
    ipv6_addr_t   ipv6_tmp = {0};
    uint32 cpr_ip_da = 0;
    uint32 cpr_ip_sa = 0;
    uint32 value = 0;
    uint32 stk_dst_port = 0;
    uint32 stk_src_port = 0;
    uint16 bulk_mask_bitmap = 0;
    hash_data_bulk_tm_t hash_data_bulk;
    uint16 hash_value = 0;
    uint16 hash_value2 = 0;
    uint32 tmp_value[SYS_DIAG_LB_HASH_GEN_HASH_NUM + SYS_DIAG_LB_HASH_GEN_HASH_NUM_MERGE] = {0};
    uint16 svlan_id = 0;
    uint16 cvlan_id = 0;
    uint32 hash_data[SYS_DIAG_LB_HASH_DATA_LEN/4] = {0};
    uint32 hash_key[SYS_DIAG_LB_HASH_DATA_LEN/4] = {0};
    uint32 hash_mask[SYS_DIAG_LB_HASH_DATA_LEN/4] = {0};

    cmd = DRV_IOR(IpeHashCtl0_t+p_gen_lb_hash->select_id*(IpeHashCtl1_t-IpeHashCtl0_t), DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, ds));
    cmd = DRV_IOR(IpePreLookupCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &pre_lookup_ctl));

    sal_memset(&hash_data_bulk, 0, sizeof(hash_data_bulk));
    SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_L3_TYPE, CTC_PARSER_L3_TYPE_NONE, layer3_type);

    ipv4_hash_en = (layer3_type == CTC_PARSER_L3_TYPE_IPV4) && (!GetIpeHashCtl0(V, disableIpv4Hash_f, ds));
    ipv6_hash_en = (layer3_type == CTC_PARSER_L3_TYPE_IPV6) && (!GetIpeHashCtl0(V, disableIpv6Hash_f, ds));
    /*mpls_hash_en = ((layer3_type == CTC_PARSER_L3_TYPE_MPLS) || (layer3_type == CTC_PARSER_L3_TYPE_MPLS_MCAST)) && (!GetIpeHashCtl0(V, disableMplsHash_f, ds));*/

    if (layer3_type == CTC_PARSER_L3_TYPE_IPV6)
    {
        SYS_DIAG_GET_LB_HASH_FIELD_EXT(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_IPV6_DA, &ipv6_tmp, sizeof(ipv6_addr_t));
        SYS_USW_REVERT_IP6(ipv6_da, ipv6_tmp);
        SYS_DIAG_GET_LB_HASH_FIELD_EXT(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_IPV6_SA, &ipv6_tmp, sizeof(ipv6_addr_t));
        SYS_USW_REVERT_IP6(ipv6_sa, ipv6_tmp);
    }

    /*compute compressipsa/ipda*/
    if(GetIpeHashCtl0(V, ipv6AddrCompressMode_f, ds))
    {
        cpr_ip_sa = ipv6_sa[3] ^ ipv6_sa[2] ^ ipv6_sa[1] ^ ipv6_sa[0];
        cpr_ip_da = ipv6_da[3] ^ ipv6_da[2] ^ ipv6_da[1] ^ ipv6_da[0];
    }
    else
    {
        cpr_ip_sa = ipv6_sa[0];
        cpr_ip_da = ipv6_da[0];
    }

    if (0 == GetIpeHashCtl0(V, vidDataSel_f, ds) || (1 == GetIpeHashCtl0(V, vidDataSel_f, ds)))
    {
        SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_SVLAN_ID, 0, svlan_id);
        SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_CVLAN_ID, 0, cvlan_id);
    }

    if(ipv4_hash_en)
    {
        /*ipv4TunnelHashUseOuter, not support inner,so only use disableForceInnerHash*/
        if(1/*GetIpeHashCtl0(V, disableForceInnerHash_f, ds)*/)
        {
            uint8 layer4_user_type = 0;
            uint8 layer4_type = 0;
            uint8 is_vxlan = 0;
            uint8 outer_ipv4_swap = 0;
            uint32 ipv4_sa = 0;
            uint32 ipv4_da = 0;
            uint8 ip_frag = 0;
            uint16 l4_src_port = 0;
            uint16 l4_dst_port = 0;
            uint32 vxlan_vni = 0;
            SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_L4_USER_TYPE, CTC_PARSER_L4_USER_TYPE_NONE, layer4_user_type);
            SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_L4_TYPE, CTC_PARSER_L4_TYPE_NONE, layer4_type);
            SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_IP_SA, 0, ipv4_sa);
            SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_IP_DA, 0, ipv4_da);

            is_vxlan = (layer4_user_type == CTC_PARSER_L4_USER_TYPE_UDP_VXLAN) && (layer4_type == CTC_PARSER_L4_TYPE_UDP);
            p_gen_lb_hash->is_vxlan = is_vxlan;
            outer_ipv4_swap = GetIpeHashCtl0(V, outerIpv4SymmetricHashEn_f, ds) && (ipv4_sa > ipv4_da);
            if((layer4_type == CTC_PARSER_L4_TYPE_TCP) || (layer4_type == CTC_PARSER_L4_TYPE_UDP) || (layer4_type == CTC_PARSER_L4_TYPE_SCTP) || (layer4_type == CTC_PARSER_L4_TYPE_DCCP))
            {
                hash_data_template2_1_tm_t hash_data_template2_1;
                sal_memset(&hash_data_template2_1, 0, sizeof(hash_data_template2_1));
                if(outer_ipv4_swap)
                {
                    hash_data_template2_1.gbulk4_ip_sa_low = ipv4_da&0xFFFF;
                    hash_data_template2_1.gbulk5_ip_sa_high = (ipv4_da>>16)&0xFFFF;
                    hash_data_template2_1.gbulk6_ip_da_low = ipv4_sa&0xFFFF;
                    hash_data_template2_1.gbulk7_ip_da_high = (ipv4_sa>>16)&0xFFFF;
                }
                else
                {
                    hash_data_template2_1.gbulk4_ip_sa_low = ipv4_sa&0xFFFF;
                    hash_data_template2_1.gbulk5_ip_sa_high = (ipv4_sa>>16)&0xFFFF;
                    hash_data_template2_1.gbulk6_ip_da_low = ipv4_da&0xFFFF;
                    hash_data_template2_1.gbulk7_ip_da_high = (ipv4_da>>16)&0xFFFF;
                }
                SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_IP_PROTOCOL, 0, hash_data_template2_1.gbulk8_l4_protocol);
                SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_IP_FRAG, 0, ip_frag);
                if(0 == ip_frag)
                {
                    SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_L4_SRC_PORT, 0, l4_src_port);
                    SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_L4_DST_PORT, 0, l4_dst_port);
                    hash_data_template2_1.gbulk9_l4_src_port = l4_src_port;
                    hash_data_template2_1.gbulk10_l4_dst_port = l4_dst_port;
                    if(GetIpeHashCtl0(V, outerIpv4SymmetricHashEn_f, ds))
                    {
                        if(outer_ipv4_swap)
                        {
                            hash_data_template2_1.gbulk9_l4_src_port = l4_dst_port;
                            hash_data_template2_1.gbulk10_l4_dst_port = l4_src_port;
                        }
                        if(is_vxlan && GetIpeHashCtl0(V, symmetricHashIpv4VxlanMaskL4Info_f, ds))
                        {
                            hash_data_template2_1.gbulk9_l4_src_port = 0;
                            hash_data_template2_1.gbulk10_l4_dst_port = 0;
                        }
                    }
                }
                hash_data_template2_1.gbulk11_vid = svlan_id&0xFFF;
                hash_data_template2_1.gbulk12_udf_low = 0;
                hash_data_template2_1.gbulk13_udf_high = 0;
                if(is_vxlan)
                {
                    if(GetIpeHashCtl0(V, v4VxlanOuterL3HashUdfFieldUseVni_f, ds))
                    {
                        SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_VN_ID, 0, vxlan_vni);
                        hash_data_template2_1.gbulk12_udf_low = vxlan_vni&0xFFFF;
                        hash_data_template2_1.gbulk13_udf_high = (vxlan_vni>>16)&0xFF;
                    }
                    bulk_mask_bitmap = GetIpeHashCtl0(V, ipv4VxlanBulkBitmap_f, ds);
                }
                else if((ip_frag == 0) && (l4_dst_port == l4_src_port))
                {
                    bulk_mask_bitmap = GetIpeHashCtl0(V, ipv4TcpUdpBulkBitmap0_f, ds);
                }
                else
                {
                    bulk_mask_bitmap = GetIpeHashCtl0(V, ipv4TcpUdpBulkBitmap1_f, ds);
                }

                sal_memcpy(hash_data_bulk.bulk13_to4_data, &hash_data_template2_1, sizeof(hash_data_template2_1));
                gen_hash_key_valid = 1;
            }
            else if(layer4_type == CTC_PARSER_L4_TYPE_GRE)
            {
                uint16 gre_type = 0;
                uint32 nvgre_vsid = 0;
                uint32 gre_key = 0;
                uint8 is_nvgre = 0;
                hash_data_template2_2_tm_t hash_data_template2_2;
                sal_memset(&hash_data_template2_2, 0, sizeof(hash_data_template2_2));
                if(outer_ipv4_swap)
                {
                    hash_data_template2_2.gbulk4_ip_sa_low = ipv4_da&0xFFFF;
                    hash_data_template2_2.gbulk5_ip_sa_high = (ipv4_da>>16)&0xFFFF;
                    hash_data_template2_2.gbulk6_ip_da_low = ipv4_sa&0xFFFF;
                    hash_data_template2_2.gbulk7_ip_da_high = (ipv4_sa>>16)&0xFFFF;
                }
                else
                {
                    hash_data_template2_2.gbulk4_ip_sa_low = ipv4_sa&0xFFFF;
                    hash_data_template2_2.gbulk5_ip_sa_high = (ipv4_sa>>16)&0xFFFF;
                    hash_data_template2_2.gbulk6_ip_da_low = ipv4_da&0xFFFF;
                    hash_data_template2_2.gbulk7_ip_da_high = (ipv4_da>>16)&0xFFFF;
                }
                SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_GRE_PROTOCOL_TYPE, 0, gre_type);
                hash_data_template2_2.gbulk8_gre_protocol_type = gre_type;
                SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_MAX_UINT32_VALUE, 0, gre_key);
                is_nvgre = (CTC_MAX_UINT32_VALUE == gre_key)?0:1;
                p_gen_lb_hash->is_nvgre = is_nvgre;
                if(is_nvgre && GetIpeHashCtl0(V, awaredNvgre_f, ds))
                {
                    SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_VN_ID, 0, nvgre_vsid);
                    hash_data_template2_2.gbulk9_gre_key_low = nvgre_vsid&0xFFFF;
                    hash_data_template2_2.gbulk10_gre_key_high = (nvgre_vsid>>16)&0xFF;
                }
                else
                {
                    SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_GRE_KEY, 0, gre_key);
                    hash_data_template2_2.gbulk9_gre_key_low = gre_key&0xFFFF;
                    hash_data_template2_2.gbulk10_gre_key_high = (gre_key>>16)&0xFFFF;
                }
                hash_data_template2_2.gbulk11_vid = svlan_id&0xFFF;
                hash_data_template2_2.gbulk12_udf_low = 0;
                hash_data_template2_2.gbulk13_udf_high = 0;
                if(is_nvgre && GetIpeHashCtl0(V, awaredNvgre_f, ds))
                {
                    bulk_mask_bitmap = GetIpeHashCtl0(V, ipv4NvgreBulkBitmap_f, ds);
                }
                else
                {
                    bulk_mask_bitmap = GetIpeHashCtl0(V, ipv4GreBulkBitmap_f, ds);
                }
                sal_memcpy(&hash_data_bulk.bulk13_to4_data, &hash_data_template2_2, sizeof(hash_data_template2_2));
                gen_hash_key_valid = 1;
            }
            else
            {
                hash_data_template2_tm_t hash_data_template2;
                sal_memset(&hash_data_template2, 0, sizeof(hash_data_template2));
                if(outer_ipv4_swap)
                {
                    hash_data_template2.gbulk4_ip_sa_low = ipv4_da&0xFFFF;
                    hash_data_template2.gbulk5_ip_sa_high = (ipv4_da>>16)&0xFFFF;
                    hash_data_template2.gbulk6_ip_da_low = ipv4_sa&0xFFFF;
                    hash_data_template2.gbulk7_ip_da_high = (ipv4_sa>>16)&0xFFFF;
                }
                else
                {
                    hash_data_template2.gbulk4_ip_sa_low = ipv4_sa&0xFFFF;
                    hash_data_template2.gbulk5_ip_sa_high = (ipv4_sa>>16)&0xFFFF;
                    hash_data_template2.gbulk6_ip_da_low = ipv4_da&0xFFFF;
                    hash_data_template2.gbulk7_ip_da_high = (ipv4_da>>16)&0xFFFF;
                }
                SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_IP_PROTOCOL, 0, hash_data_template2.gbulk8_l4_protocol);
                hash_data_template2.gbulk9_l4_info1 = 0;
                hash_data_template2.gbulk10_l4_info2 = 0;
                hash_data_template2.gbulk11_vid = svlan_id&0xFFF;
                hash_data_template2.gbulk12_ext_info1 = 0;
                hash_data_template2.gbulk13_ext_info2 = 0;
                bulk_mask_bitmap = GetIpeHashCtl0(V, ipv4OuterL3BulkBitmap_f, ds);
                sal_memcpy(&hash_data_bulk.bulk13_to4_data, &hash_data_template2, sizeof(hash_data_template2));
                gen_hash_key_valid = 1;
            }
        }
        else
        {
            /*for now not support inner hash*/
            SYS_DIAG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "not supoort ipv4 packet inner lb hash\n");
            return CTC_E_NOT_SUPPORT;
        }
    }
    else if(ipv6_hash_en)
    {
        if(1 /*GetIpeHashCtl0(V, disableForceInnerHash_f, ds)*/)
        {
            uint8 layer4_user_type = 0;
            uint8 layer4_type = 0;
            uint8 is_vxlan = 0;
            uint8 outer_ipv6_swap = 0;
            uint8 ip_frag = 0;
            uint16 l4_src_port = 0;
            uint16 l4_dst_port = 0;
            uint32 ipv6_flow_label = 0;
            uint32 vxlan_vni = 0;
            SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_L4_USER_TYPE, CTC_PARSER_L4_USER_TYPE_NONE, layer4_user_type);
            SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_L4_TYPE, CTC_PARSER_L4_TYPE_NONE, layer4_type);

            is_vxlan = (layer4_user_type == CTC_PARSER_L4_USER_TYPE_UDP_VXLAN) && (layer4_type == CTC_PARSER_L4_TYPE_UDP);
            p_gen_lb_hash->is_vxlan = is_vxlan;
            outer_ipv6_swap = GetIpeHashCtl0(V, outerIpv6SymmetricHashEn_f, ds) && ((ipv6_sa[3] > ipv6_da[3])
                || ((ipv6_sa[3] == ipv6_da[3]) && (ipv6_sa[2] > ipv6_da[2])) 
                || ((ipv6_sa[3] == ipv6_da[3]) && (ipv6_sa[2] == ipv6_da[2]) && (ipv6_sa[1] > ipv6_da[1]))
                || ((ipv6_sa[3] == ipv6_da[3]) && (ipv6_sa[2] == ipv6_da[2]) && (ipv6_sa[1] == ipv6_da[1]) && (ipv6_sa[0] > ipv6_da[0])));
            if((layer4_type == CTC_PARSER_L4_TYPE_TCP) || (layer4_type == CTC_PARSER_L4_TYPE_UDP) || (layer4_type == CTC_PARSER_L4_TYPE_SCTP) || (layer4_type == CTC_PARSER_L4_TYPE_DCCP))
            {
                hash_data_template2_tm_t hash_data_template2;
                sal_memset(&hash_data_template2, 0, sizeof(hash_data_template2));
                if(outer_ipv6_swap)
                {
                    hash_data_template2.gbulk4_ip_sa_low = cpr_ip_da&0xFFFF;
                    hash_data_template2.gbulk5_ip_sa_high = (cpr_ip_da>>16)&0xFFFF;
                    hash_data_template2.gbulk6_ip_da_low = cpr_ip_sa&0xFFFF;
                    hash_data_template2.gbulk7_ip_da_high = (cpr_ip_sa>>16)&0xFFFF;
                }
                else
                {
                    hash_data_template2.gbulk4_ip_sa_low = cpr_ip_sa&0xFFFF;
                    hash_data_template2.gbulk5_ip_sa_high = (cpr_ip_sa>>16)&0xFFFF;
                    hash_data_template2.gbulk6_ip_da_low = cpr_ip_da&0xFFFF;
                    hash_data_template2.gbulk7_ip_da_high = (cpr_ip_da>>16)&0xFFFF;
                }
                SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_IP_PROTOCOL, 0, hash_data_template2.gbulk8_l4_protocol);
                SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_IP_FRAG, 0, ip_frag);
                SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_L4_SRC_PORT, 0, l4_src_port);
                SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_L4_DST_PORT, 0, l4_dst_port);
                if(ip_frag == 0)
                {
                    hash_data_template2.gbulk9_l4_info1 = l4_src_port;
                    hash_data_template2.gbulk10_l4_info2 = l4_dst_port;
                    if(GetIpeHashCtl0(V, outerIpv6SymmetricHashEn_f, ds))
                    {
                        if(outer_ipv6_swap)
                        {
                            hash_data_template2.gbulk9_l4_info1 = l4_dst_port;
                            hash_data_template2.gbulk10_l4_info2 = l4_src_port;
                        }
                        if(is_vxlan && GetIpeHashCtl0(V, symmetricHashIpv6VxlanMaskL4Info_f, ds))
                        {
                            hash_data_template2.gbulk9_l4_info1 = 0;
                            hash_data_template2.gbulk10_l4_info2 = 0;
                        }
                    }
                }
                SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_IPV6_FLOW_LABEL, 0, ipv6_flow_label);
                hash_data_template2.gbulk11_vid = svlan_id&0xFFF;
                hash_data_template2.gbulk12_ext_info1 = GetIpeHashCtl0(V, bulk12And13Ipv6UseFlowLabel0_f, ds)? ipv6_flow_label&0xFFFF : 0;
                hash_data_template2.gbulk13_ext_info2 = GetIpeHashCtl0(V, bulk12And13Ipv6UseFlowLabel0_f, ds)? (ipv6_flow_label>>16)&0xF : 0;
                if(is_vxlan)
                {
                    if(GetIpeHashCtl0(V, v6VxlanOuterL3HashUdfFieldUseVni_f, ds))
                    {
                        SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_VN_ID, 0, vxlan_vni);
                        hash_data_template2.gbulk12_ext_info1 = vxlan_vni&0xFFFF;
                        hash_data_template2.gbulk13_ext_info2 = (vxlan_vni>>16)&0xFF;
                    }
                    bulk_mask_bitmap = GetIpeHashCtl0(V, ipv6VxlanBulkBitmap_f, ds);
                }
                else if((ip_frag == 0) && (l4_src_port == l4_dst_port))
                {
                    bulk_mask_bitmap = GetIpeHashCtl0(V, ipv6TcpUdpBulkBitmap0_f, ds);
                }
                else
                {
                    bulk_mask_bitmap = GetIpeHashCtl0(V, ipv6TcpUdpBulkBitmap1_f, ds);
                }
                sal_memcpy(hash_data_bulk.bulk13_to4_data, &hash_data_template2, sizeof(hash_data_template2));
                gen_hash_key_valid = 1;
            }
            else if(layer4_type == CTC_PARSER_L4_TYPE_GRE)
            {
                uint16 gre_type = 0;
                uint32 nvgre_vsid = 0;
                uint32 gre_key = 0;
                uint8 is_nvgre = 0;
                uint32 ipv6_flow_label = 0;
                hash_data_template2_2_tm_t hash_data_template2_2;
                sal_memset(&hash_data_template2_2, 0, sizeof(hash_data_template2_2));
                if(outer_ipv6_swap)
                {
                    hash_data_template2_2.gbulk4_ip_sa_low = cpr_ip_da&0xFFFF;
                    hash_data_template2_2.gbulk5_ip_sa_high = (cpr_ip_da>>16)&0xFFFF;
                    hash_data_template2_2.gbulk6_ip_da_low = cpr_ip_sa&0xFFFF;
                    hash_data_template2_2.gbulk7_ip_da_high = (cpr_ip_sa>>16)&0xFFFF;
                }
                else
                {
                    hash_data_template2_2.gbulk4_ip_sa_low = cpr_ip_sa&0xFFFF;
                    hash_data_template2_2.gbulk5_ip_sa_high = (cpr_ip_sa>>16)&0xFFFF;
                    hash_data_template2_2.gbulk6_ip_da_low = cpr_ip_da&0xFFFF;
                    hash_data_template2_2.gbulk7_ip_da_high = (cpr_ip_da>>16)&0xFFFF;
                }
                SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_GRE_PROTOCOL_TYPE, 0, gre_type);
                hash_data_template2_2.gbulk8_gre_protocol_type = gre_type;
                SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_NVGRE_KEY, CTC_MAX_UINT32_VALUE, gre_key);
                is_nvgre = (CTC_MAX_UINT32_VALUE == gre_key)?0:1;
                p_gen_lb_hash->is_nvgre = is_nvgre;
                if(is_nvgre && GetIpeHashCtl0(V, awaredNvgre_f, ds))
                {
                    SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_VN_ID, 0, nvgre_vsid);
                    hash_data_template2_2.gbulk9_gre_key_low = nvgre_vsid&0xFFFF;
                    hash_data_template2_2.gbulk10_gre_key_high = (nvgre_vsid>>16)&0xFF;
                }
                else
                {
                    SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_GRE_KEY, 0, gre_key);
                    hash_data_template2_2.gbulk9_gre_key_low = gre_key&0xFFFF;
                    hash_data_template2_2.gbulk10_gre_key_high = (gre_key>>16)&0xFFFF;
                }

                SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_IPV6_FLOW_LABEL, 0, ipv6_flow_label);
                hash_data_template2_2.gbulk11_vid = svlan_id&0xFFF;
                hash_data_template2_2.gbulk12_udf_low =  GetIpeHashCtl0(V, bulk12And13Ipv6UseFlowLabel0_f, ds)? ipv6_flow_label&0xFFFF : 0;
                hash_data_template2_2.gbulk13_udf_high = GetIpeHashCtl0(V, bulk12And13Ipv6UseFlowLabel0_f, ds)? (ipv6_flow_label>>16)&0xF : 0;
                if(is_nvgre && GetIpeHashCtl0(V, awaredNvgre_f, ds))
                {
                    bulk_mask_bitmap = GetIpeHashCtl0(V, ipv6NvgreBulkBitmap_f, ds);
                }
                else
                {
                    bulk_mask_bitmap = GetIpeHashCtl0(V, ipv6GreBulkBitmap_f, ds);
                }
                sal_memcpy(&hash_data_bulk.bulk13_to4_data, &hash_data_template2_2, sizeof(hash_data_template2_2));
                gen_hash_key_valid = 1;
            }
            else
            {
                hash_data_template2_tm_t hash_data_template2;
                sal_memset(&hash_data_template2, 0, sizeof(hash_data_template2));
                if(outer_ipv6_swap)
                {
                    hash_data_template2.gbulk4_ip_sa_low = cpr_ip_da&0xFFFF;
                    hash_data_template2.gbulk5_ip_sa_high = (cpr_ip_da>>16)&0xFFFF;
                    hash_data_template2.gbulk6_ip_da_low = cpr_ip_sa&0xFFFF;
                    hash_data_template2.gbulk7_ip_da_high = (cpr_ip_sa>>16)&0xFFFF;
                }
                else
                {
                    hash_data_template2.gbulk4_ip_sa_low = cpr_ip_sa&0xFFFF;
                    hash_data_template2.gbulk5_ip_sa_high = (cpr_ip_sa>>16)&0xFFFF;
                    hash_data_template2.gbulk6_ip_da_low = cpr_ip_da&0xFFFF;
                    hash_data_template2.gbulk7_ip_da_high = (cpr_ip_da>>16)&0xFFFF;
                }
                SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_IP_PROTOCOL, 0, hash_data_template2.gbulk8_l4_protocol);
                hash_data_template2.gbulk9_l4_info1 = 0;
                hash_data_template2.gbulk10_l4_info2 = 0;
                hash_data_template2.gbulk11_vid = svlan_id&0xFFF;
                SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_IPV6_FLOW_LABEL, 0, ipv6_flow_label);
                hash_data_template2.gbulk12_ext_info1 = GetIpeHashCtl0(V, bulk12And13Ipv6UseFlowLabel0_f, ds)? ipv6_flow_label&0xFFFF : 0;
                hash_data_template2.gbulk13_ext_info2 = GetIpeHashCtl0(V, bulk12And13Ipv6UseFlowLabel0_f, ds)? (ipv6_flow_label>>16)&0xF : 0;
                bulk_mask_bitmap = GetIpeHashCtl0(V, ipv6OuterL3BulkBitmap_f, ds);
                sal_memcpy(&hash_data_bulk.bulk13_to4_data, &hash_data_template2, sizeof(hash_data_template2));
                gen_hash_key_valid = 1;
            }
        }
        else
        {
            /*for now not support inner hash*/
            SYS_DIAG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "not supoort ipv6 packet inner lb hash\n");
        }
    }
    else if ((layer3_type == CTC_PARSER_L3_TYPE_MPLS) || (layer3_type == CTC_PARSER_L3_TYPE_FCOE) || (layer3_type == CTC_PARSER_L3_TYPE_TRILL))
    {
        SYS_DIAG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "not supoort not ipv4 or ipv6 packet lb hash\n");
        return CTC_E_NOT_SUPPORT;
    }

    if(!gen_hash_key_valid)
    {
        mac_addr_t sw_sa_mac = {0};
        mac_addr_t sw_da_mac = {0};
        hw_mac_addr_t hw_mac = {0};
        uint8 stk_hdr_exist = 0;
        hash_data_template1_tm_t hash_data_template1;
        sal_memset(&hash_data_template1, 0, sizeof(hash_data_template1));

        SYS_DIAG_GET_LB_HASH_FIELD_EXT(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_MAC_SA, &sw_sa_mac, sizeof(mac_addr_t));
        SYS_USW_SET_HW_MAC(hw_mac, (uint8*)sw_sa_mac);
        hash_data_template1.gbulk4_mac_sa_low = hw_mac[0]&0xFFFF;
        hash_data_template1.gbulk5_mac_sa_middle = (hw_mac[0]>>16)&0xFFFF;
        hash_data_template1.gbulk6_mac_sa_high = hw_mac[1]&0xFFFF;
        SYS_DIAG_GET_LB_HASH_FIELD_EXT(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_MAC_DA, &sw_da_mac, sizeof(mac_addr_t));
        SYS_USW_SET_HW_MAC(hw_mac, (uint8*)sw_da_mac);
        hash_data_template1.gbulk7_mac_da_low = hw_mac[0]&0xFFFF;
        hash_data_template1.gbulk8_mac_da_middle = (hw_mac[0]>>16)&0xFFFF;
        hash_data_template1.gbulk9_mac_da_high = hw_mac[1]&0xFFFF;
        SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_ETHER_TYPE, 0, hash_data_template1.gbulk10_ether_type);
        hash_data_template1.gbulk11_vid_info1 = svlan_id&0xFFF;
        hash_data_template1.gbulk12_vid_info2 = cvlan_id&0xFFF;
        hash_data_template1.gbulk13_tbd = 0;
        SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_STK_HDR_EXIST, 0, stk_hdr_exist);
        bulk_mask_bitmap = stk_hdr_exist?GetIpeHashCtl0(V, defaultBulkBitmap_f, ds):GetIpeHashCtl0(V, outerL2BulkBitmap_f, ds);
        sal_memcpy(&hash_data_bulk.bulk13_to4_data, &hash_data_template1, sizeof(hash_data_template1));
    }

    /*overwrite mask bitmap for arctic*/
    if (DRV_FROM_AT(lchip))
    {
        step = IpeHashCtl0_u_g2_1_overwriteBulkMaskValid_f - IpeHashCtl0_u_g2_0_overwriteBulkMaskValid_f;
        if (GetIpeHashCtl0(V, u_g2_0_overwriteBulkMaskValid_f + step * mask_profile_id, ds))
        {
            bulk_mask_bitmap = GetIpeHashCtl0(V, u_g2_0_bulkBitmap_f + step * mask_profile_id, ds);
        }
    }

    SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_STK_DST_GPORT, 0, stk_dst_port);
    SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_STK_SRC_GPORT, CTC_MAX_UINT32_VALUE, stk_src_port);
    if (CTC_MAX_UINT32_VALUE == stk_src_port)
    {
        hash_data_bulk.ubulk0_g1_src_local_port = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_gen_lb_hash->src_gport);
        hash_data_bulk.ubulk1_g1_src_chip_id = SYS_MAP_CTC_GPORT_TO_GCHIP(p_gen_lb_hash->src_gport);
    }
    else
    {
        hash_data_bulk.ubulk0_g1_src_local_port = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(stk_src_port);
        hash_data_bulk.ubulk1_g1_src_chip_id = SYS_MAP_CTC_GPORT_TO_GCHIP(stk_src_port);
    }
    hash_data_bulk.ubulk2_g1_dst_local_port = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(stk_dst_port);
    hash_data_bulk.ubulk3_g1_dst_chip_id = SYS_MAP_CTC_GPORT_TO_GCHIP(stk_dst_port);
    hash_data_bulk.ubulk14_g1_data0 = GetIpeHashCtl0(V, hashSeed_f, ds)&0xFFFF;
    hash_data_bulk.ubulk15_g1_data1 = (GetIpeHashCtl0(V, hashSeed_f, ds)>>16)&0xFFFF;
    if(DRV_FROM_TMM(lchip))
    {
        if(GetIpeHashCtl0(V, enableUdfMode_f, ds) == 1)
        {
            hash_data_bulk.ubulk14_g1_data0 = 0;
            hash_data_bulk.ubulk15_g1_data1 = 0;
        }
        else if(GetIpeHashCtl0(V, enableUdfMode_f, ds) == 2)
        {
            hash_data_bulk.ubulk1_g1_src_chip_id = 0;
            hash_data_bulk.ubulk0_g1_src_local_port = 0;
        }
    }
    sal_memcpy(hash_data, &hash_data_bulk, sizeof(hash_data_bulk));
    value = GetIpeHashCtl0(V, hashSeedMask_f, ds);
    /*hashSeedMask to set hash_mask[14,15]*/
    if (CTC_IS_BIT_SET(value, 0))
    {
        bulk_mask_bitmap |= 0x4000;
    }
    if (CTC_IS_BIT_SET(value, 1))
    {
        bulk_mask_bitmap |= 0x8000;
    }

    for (idx=0; idx<SYS_DIAG_LB_HASH_DATA_LEN/4; idx++)
    {
        if (CTC_IS_BIT_SET(bulk_mask_bitmap, 2*idx))
        {
            hash_mask[idx] |= 0xFFFF;
        }
        if (CTC_IS_BIT_SET(bulk_mask_bitmap, 2*idx+1))
        {
            hash_mask[idx] |= 0xFFFF0000;
        }
    }

    for (idx=0; idx<SYS_DIAG_LB_HASH_DATA_LEN/4; idx++)
    {
        hash_key[idx] = hash_data[idx]&hash_mask[idx];
    }

    if (DRV_IS_TSINGMA(lchip))
    {
        _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_CRC8_POLY1, 0, &tmp_value[0]);
        _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_CRC8_POLY2, 0, &tmp_value[1]);
        _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_XOR8, 0, &tmp_value[2]);
        _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_CRC10_POLY1, 0, &tmp_value[3]);
        _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_CRC10_POLY4, 0, &tmp_value[4]);
        _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_XOR16, 0, &tmp_value[5]);
        _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_CRC16_POLY1, 0, &tmp_value[6]);
        _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_CRC16_POLY2, 0, &tmp_value[7]);
        _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_CRC16_POLY3, 0, &tmp_value[8]);
        _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_CRC16_POLY4, 0, &tmp_value[9]);
        value = GetIpeHashCtl0(V, hashPolySelectA_f, ds);
        value = value>=SYS_DIAG_LB_HASH_GEN_HASH_NUM?(SYS_DIAG_LB_HASH_GEN_HASH_NUM-1):value;
        p_gen_lb_hash->hash_val1 = tmp_value[value]&0xFFFF;
    
        value = GetIpeHashCtl0(V, hashPolySelectB_f, ds);
        value = (value>=SYS_DIAG_LB_HASH_GEN_HASH_NUM)?(SYS_DIAG_LB_HASH_GEN_HASH_NUM-1):value;
        p_gen_lb_hash->hash_val2 = tmp_value[value]&0xFFFF;
    }
    else
    {
        _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_XOR8, 0, &tmp_value[0]);
        _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_XOR16, 0, &tmp_value[1]);
        _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_CRC8_POLY1, 0, &tmp_value[2]);
        _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_CRC16_POLY2, 0, &tmp_value[3]);
        _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_CRC16_BISYNC, 0, &tmp_value[4]);
        _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_CRC16_CCITT, 0, &tmp_value[5]);
        _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_CRC32_POLY1, 0, &tmp_value[6]);
        if (DRV_FROM_AT(lchip)) /*for hash merge*/
        {
            _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_CRC8_POLY1, 1, &tmp_value[7]);
            _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_CRC16_POLY2, 1, &tmp_value[8]);
            _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_CRC16_BISYNC, 1, &tmp_value[9]);
            _sys_usw_diag_gen_hash((uint8*)hash_key, SYS_DIAG_LB_HASH_DATA_LEN*8, SYS_DIAG_HASH_POLY_TYPE_CRC16_CCITT, 1, &tmp_value[10]);
        }
        value = GetIpeHashCtl0(V, hashPolySelectA_f, ds);
        switch(value)
        {
            case 1:
                hash_value = ((tmp_value[4]&0xFF00) | (tmp_value[0]&0xFF));
                hash_value2 = ((tmp_value[4]&0xFF00) | (tmp_value[0]&0xFF));
                break;
            case 2:
                hash_value = tmp_value[0]&0xFFFF;
                hash_value2 = tmp_value[0]&0xFFFF;
                break;
            case 5:
                hash_value = tmp_value[1]&0xFFFF;
                hash_value2 = tmp_value[1]&0xFFFF;
                break;
            case 6:
                hash_value = tmp_value[2]&0xFFFF;
                hash_value2 = tmp_value[7]&0xFFFF;
                break;
            case 7:
                hash_value = tmp_value[3]&0xFFFF;
                hash_value2 = tmp_value[8]&0xFFFF;
                break;  
            case 10 :
                hash_value = tmp_value[4]&0xFFFF;
                hash_value2 = tmp_value[9]&0xFFFF;
                break;
            case 11 :
                hash_value = tmp_value[5]&0xFFFF;
                hash_value2 = tmp_value[10]&0xFFFF;
                break;
            case 12 :
                hash_value = tmp_value[6]&0xFFFF;
                hash_value2 = tmp_value[6]&0xFFFF;
                break;
            case 13 :
                hash_value = (tmp_value[6]>>16)&0xFFFF;
                hash_value2 = (tmp_value[6]>>16)&0xFFFF;
                break;   
            default:
                break;
        }
        p_gen_lb_hash->hash_val1 = hash_value;
        p_gen_lb_hash->hash_val2 = hash_value2;
    }

    return CTC_E_NONE;
}

STATIC void
_sys_tsingma_diag_select_hash_value(uint16* hash_value, uint8 hash_select, uint8 hash_offset, uint8 rgt_shift_ctl, uint16* p_hash_value)
{
    uint16 hash_data = 0;

    hash_data = hash_value[hash_select];

    if(rgt_shift_ctl)
    {
        *p_hash_value = (hash_data >> hash_offset)| (hash_data << (sizeof(hash_data)*8-hash_offset));
    }
    else
    {
        *p_hash_value = hash_data >> hash_offset;
    }
}

STATIC int32
_sys_tsingma_diag_check_lb_hash_field_param(uint8 lchip,  ctc_field_key_t* p_field_list, uint32 field_cnt)
{
    int32 ret = CTC_E_NONE;
    uint32 field_id = 0;
    ctc_field_key_t* p_key_field = NULL;

    for (field_id=0; field_id<field_cnt; field_id++)
    {
        p_key_field = (ctc_field_key_t*)p_field_list + field_id;
        switch(p_key_field->type)
        {
            case CTC_FIELD_KEY_L3_TYPE:
                CTC_MAX_VALUE_CHECK(p_key_field->data, MAX_CTC_PARSER_L3_TYPE-1);
                break;
            case CTC_FIELD_KEY_L4_TYPE:
                CTC_MAX_VALUE_CHECK(p_key_field->data, MAX_CTC_PARSER_L4_TYPE-1);
                break;
            case CTC_FIELD_KEY_L4_USER_TYPE:
                CTC_MAX_VALUE_CHECK(p_key_field->data, MAX_CTC_PARSER_L4_USER_TYPE-1);
                break;
            case CTC_FIELD_KEY_IP_PROTOCOL:
                CTC_MAX_VALUE_CHECK(p_key_field->data, 0xFF);
                break;
            case CTC_FIELD_KEY_L4_SRC_PORT:
            case CTC_FIELD_KEY_L4_DST_PORT:
                CTC_MAX_VALUE_CHECK(p_key_field->data, 0xFFFF);
                break;
            case CTC_FIELD_KEY_IP_FRAG:
                CTC_MAX_VALUE_CHECK(p_key_field->data, CTC_IP_FRAG_MAX - 1);
                break;

            case CTC_FIELD_KEY_IPV6_FLOW_LABEL:
                CTC_MAX_VALUE_CHECK(p_key_field->data, 0xFFFFF);
                break;
            case CTC_FIELD_KEY_ETHER_TYPE:
                CTC_MAX_VALUE_CHECK(p_key_field->data, 0xFFFF);
                break;
            case CTC_FIELD_KEY_SVLAN_ID:
            case CTC_FIELD_KEY_CVLAN_ID:
                CTC_MAX_VALUE_CHECK(p_key_field->data, 0xFFF);
                break;
            case CTC_FIELD_KEY_GRE_PROTOCOL_TYPE:
                CTC_MAX_VALUE_CHECK(p_key_field->data, 0xFFFF);
                break;
            case CTC_FIELD_KEY_VN_ID:
                CTC_MAX_VALUE_CHECK(p_key_field->data, 0xFFFFFF);
                break;
            case CTC_FIELD_KEY_GRE_KEY:
            case CTC_FIELD_KEY_NVGRE_KEY:
                CTC_MAX_VALUE_CHECK(p_key_field->data, 0xFFFFFF);
                break;
            case CTC_FIELD_KEY_STK_DST_GPORT:
            case CTC_FIELD_KEY_STK_SRC_GPORT:
                CTC_GLOBAL_PORT_CHECK(p_key_field->data);
                break;
            case CTC_FIELD_KEY_MAC_SA:
            case CTC_FIELD_KEY_MAC_DA:
            case CTC_FIELD_KEY_IP_SA:
            case CTC_FIELD_KEY_IP_DA:
            case CTC_FIELD_KEY_IPV6_SA:
            case CTC_FIELD_KEY_IPV6_DA:
            case CTC_FIELD_KEY_STK_HDR_EXIST:
                break;
            default:
                return CTC_E_INVALID_PARAM;
                break;
        }
    }


    return ret;
}
int32
sys_tsingma_diag_get_lb_hash(uint8 lchip, ctc_field_key_t* p_field_list, uint32 field_cnt, ctc_diag_lb_hash_t* p_rslt)
{
    uint8 idx = 0;
    uint16 hash_data[SYS_DIAG_LB_HASH_SEL_ID_NUM] = {0};
    uint16 hash_data2[SYS_DIAG_LB_HASH_SEL_ID_NUM + SYS_DIAG_LB_HASH_SEL_EXT_NUM] = {0};
    uint32 profile_id = 0;
    uint32 value = 0;
    ctc_lb_hash_offset_t lb_hash_offset;
    sys_tsingma_diag_lb_hash_t gen_lb_hash;
    uint8 hash_select = 0;
    uint8 hash_offset = 0;
    uint16 hash_value = 0;
    uint16 lport = 0;
    uint8  layer3_type = 0;
    uint8  layer4_type = 0;
    uint8  packet_type = 0;
    uint8  mask_profile_id = 0;
    uint8  step = 0;
    uint32 cmd = 0;
    IpePreLookupHashMap_m hash_map;

    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_rslt->src_gport, lchip, lport);
    CTC_ERROR_RETURN(_sys_tsingma_diag_check_lb_hash_field_param(lchip, p_field_list, field_cnt));
    if ((!CTC_FLAG_ISSET(p_rslt->flags, CTC_DIAG_PKT_LB_HASH_FLAGS_LINKAGG))
        && (!CTC_FLAG_ISSET(p_rslt->flags, CTC_DIAG_PKT_LB_HASH_FLAGS_ECMP)))
    {
        SYS_DIAG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "lb hash only support linkagg or ecmp!\n");
        return CTC_E_INVALID_PARAM;
    }

    sal_memset(&lb_hash_offset,0,sizeof(ctc_lb_hash_offset_t));
    sal_memset(&gen_lb_hash, 0, sizeof(sys_tsingma_diag_lb_hash_t));

    /*get packet type for merge*/
    if (DRV_FROM_AT(lchip))
    {
        SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_L3_TYPE, CTC_PARSER_L3_TYPE_NONE, layer3_type);
        SYS_DIAG_GET_LB_HASH_FIELD(lchip, p_field_list, field_cnt, CTC_FIELD_KEY_L4_TYPE, CTC_PARSER_L4_TYPE_NONE, layer4_type);
        if (CTC_PARSER_L3_TYPE_IPV4 == layer3_type)
        {
            switch (layer4_type)
            {
                case CTC_PARSER_L4_TYPE_NONE:
                case CTC_PARSER_L4_TYPE_TCP:
                    packet_type = SYS_DIAG_HASH_PACKET_TYPE_IPV4;
                    break;
                case CTC_PARSER_L4_TYPE_UDP:
                    packet_type = SYS_DIAG_HASH_PACKET_TYPE_IPV4_UDP;
                    break;
                case CTC_PARSER_L4_TYPE_GRE:
                    packet_type = SYS_DIAG_HASH_PACKET_TYPE_IPV4_GRE;
                    break;
                case CTC_PARSER_L4_TYPE_IPINIP:
                    packet_type = SYS_DIAG_HASH_PACKET_TYPE_IPV4_INNER_IPV4;
                    break;
                case CTC_PARSER_L4_TYPE_V6INIP:
                    packet_type = SYS_DIAG_HASH_PACKET_TYPE_IPV4_INNER_IPV6;
                    break;
                default:
                    return CTC_E_NOT_SUPPORT;
            }
        }
        else if (CTC_PARSER_L3_TYPE_IPV6 == layer3_type)
        {
            switch (layer4_type)
            {
                case CTC_PARSER_L4_TYPE_NONE:
                case CTC_PARSER_L4_TYPE_TCP:
                    packet_type = SYS_DIAG_HASH_PACKET_TYPE_IPV6;
                    break;
                case CTC_PARSER_L4_TYPE_UDP:
                    packet_type = SYS_DIAG_HASH_PACKET_TYPE_IPV6_UDP;
                    break;
                case CTC_PARSER_L4_TYPE_GRE:
                    packet_type = SYS_DIAG_HASH_PACKET_TYPE_IPV6_GRE;
                    break;
                case CTC_PARSER_L4_TYPE_IPINV6:
                    packet_type = SYS_DIAG_HASH_PACKET_TYPE_IPV6_INNER_IPV4;
                    break;
                case CTC_PARSER_L4_TYPE_V6INV6:
                    packet_type = SYS_DIAG_HASH_PACKET_TYPE_IPV6_INNER_IPV6;
                    break;
                default:
                    return CTC_E_NOT_SUPPORT;
            }
        }
        else
        {
            packet_type = SYS_DIAG_HASH_PACKET_TYPE_BRIDGE;
        }
        cmd = DRV_IOR(IpePreLookupHashMap_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, packet_type>>3, cmd, &hash_map);
        step = IpePreLookupHashMap_g_1_hashMaskProfileId_f - IpePreLookupHashMap_g_0_hashMaskProfileId_f;
        mask_profile_id = GetIpePreLookupHashMap(V, g_0_hashMaskProfileId_f + step * (packet_type & 0x7), &hash_map);
    }

    gen_lb_hash.src_gport = p_rslt->src_gport;
    for (idx=0; idx<MCHIP_CAP(SYS_CAP_LB_HASH_MAX_SEL_NUM); idx++)
    {
        gen_lb_hash.select_id = idx;
        CTC_ERROR_RETURN(_sys_tsingma_diag_generate_lb_hash(lchip, p_field_list, field_cnt, mask_profile_id, &gen_lb_hash));
        hash_data[idx] = gen_lb_hash.hash_val1;
        hash_data2[idx] = gen_lb_hash.hash_val2;
    }
    if(DRV_IS_TSINGMA(lchip))
    {
        for (idx=MCHIP_CAP(SYS_CAP_LB_HASH_MAX_SEL_NUM)-1; idx>0; idx--)
        {
            hash_data[idx*2+1] = hash_data2[idx];
            hash_data[idx*2] = hash_data[idx];
        }
        hash_data[1] = hash_data2[0];
    }

    /* hash merge process */
    if (DRV_FROM_AT(lchip))
    {
        IpeHashMergeCtl_m hash_merge_ctl;
        IpeHashMergeBusSel0_m merge_bus;
        IpeHashCtl0_m hash_ctl;
        uint16 input_hash_value0 = 0;
        uint16 input_hash_value1 = 0;
        uint16 merge_hash_value = 0;
        uint8  hash_merge_valid = 0;
        uint8  selector0 = 0;
        uint8  selector1 = 0;
        uint8  selector0_poly = 0;
        uint8  selector1_poly = 0;

        sal_memcpy(hash_data2, hash_data, sizeof(uint16) * MCHIP_CAP(SYS_CAP_LB_HASH_SELECT_NUM));

        cmd = DRV_IOR(IpeHashMergeCtl_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, 0, cmd, &hash_merge_ctl);

        for (idx=0; idx<MCHIP_CAP(SYS_CAP_LB_HASH_EXT_SELECT_NUM); idx++)
        {
            step = IpeHashMergeCtl_gHashMerger_1_enable_f - IpeHashMergeCtl_gHashMerger_0_enable_f;
            hash_merge_valid = GetIpeHashMergeCtl(V, gHashMerger_0_enable_f + step * idx, &hash_merge_ctl);
            selector0 = GetIpeHashMergeCtl(V, gHashMerger_0_setGeneratorId0_f + step * idx, &hash_merge_ctl);
            selector1 = GetIpeHashMergeCtl(V, gHashMerger_0_setGeneratorId1_f + step * idx, &hash_merge_ctl);

            step = IpeHashCtl1_t - IpeHashCtl0_t;
            cmd = DRV_IOR(IpeHashCtl0_t + step * selector0, DRV_ENTRY_FLAG);
            DRV_IOCTL(lchip, 0, cmd, &hash_ctl);
            selector0_poly = GetIpeHashCtl0(V, hashPolySelectA_f, &hash_ctl);
            input_hash_value0 = hash_data[selector0];
            
            cmd = DRV_IOR(IpeHashCtl0_t + step * selector1, DRV_ENTRY_FLAG);
            DRV_IOCTL(lchip, 0, cmd, &hash_ctl);
            selector1_poly = GetIpeHashCtl0(V, hashPolySelectA_f, &hash_ctl);
            input_hash_value1 = hash_data[selector1];

            /*merge en*/
            if (hash_merge_valid && (selector0_poly == selector1_poly) && GetIpeHashMergeCtl(V, supportMergePolyEn_f, &hash_merge_ctl))
            {
                if ((SYS_LB_HASHPOLY_XOR8 == selector0_poly) || (SYS_LB_HASHPOLY_XOR16 == selector0_poly))
                {
                    merge_hash_value = input_hash_value0 ^ input_hash_value1;
                }
                else
                {
                    merge_hash_value = _sys_usw_diag_crc_merge_hash(lchip, input_hash_value0, input_hash_value1, selector0_poly);
                }
                hash_data2[idx+MCHIP_CAP(SYS_CAP_LB_HASH_SELECT_NUM)] = merge_hash_value;
            }
        }

        for (idx=0; idx<SYS_DIAG_LB_HASH_SEL_ID_NUM; idx++)
        {
            uint8 hash_sel = 0;
            step = IpeHashMergeBusSel1_t - IpeHashMergeBusSel0_t;
            cmd = DRV_IOR(IpeHashMergeBusSel0_t + step * idx, DRV_ENTRY_FLAG);
            DRV_IOCTL(lchip, 0, cmd, &merge_bus);
            step = IpeHashMergeBusSel0_g_1_sel_f - IpeHashMergeBusSel0_g_0_sel_f;
            hash_sel = GetIpeHashMergeBusSel0(V, g_0_sel_f + packet_type * step, &merge_bus);

            if (0 != hash_sel)
            {
                hash_sel -= 1;
                hash_data[idx] = hash_data2[hash_sel];
            }
        }
    }

    if (CTC_FLAG_ISSET(p_rslt->flags, CTC_DIAG_PKT_LB_HASH_FLAGS_LINKAGG))
    {
        CTC_ERROR_RETURN(sys_usw_port_get_property(lchip, p_rslt->src_gport, CTC_PORT_PROP_LB_HASH_LAG_PROFILE, &profile_id));
        if (profile_id)
        {
            lb_hash_offset.hash_module = CTC_LB_HASH_MODULE_LINKAGG;
            lb_hash_offset.hash_mode = CTC_LB_HASH_MODE_STATIC;
            lb_hash_offset.fwd_type = CTC_LB_HASH_FWD_UC;
            lb_hash_offset.profile_id = profile_id;
            CTC_ERROR_RETURN(sys_usw_global_ctl_get(lchip, CTC_GLOBAL_LB_HASH_OFFSET_PROFILE, &lb_hash_offset));
            profile_id = (lb_hash_offset.offset == CTC_LB_HASH_OFFSET_DISABLE)?0:profile_id;
            value = lb_hash_offset.offset;
        }

        if (0 == profile_id)
        {
            CTC_ERROR_RETURN(sys_usw_linkagg_get_property(lchip, p_rslt->group_id, CTC_LINKAGG_PROP_LB_HASH_OFFSET, &value));
        }
        hash_select = value/16;
        hash_offset = value%16;
        _sys_tsingma_diag_select_hash_value(hash_data, hash_select, hash_offset, DRV_IS_TSINGMA(lchip)?0:1, &hash_value);
        p_rslt->hash_val = hash_value&0xFF;
        CTC_ERROR_RETURN(sys_usw_linkagg_get_member_with_hash(lchip, p_rslt->group_id, hash_value, &p_rslt->dest_gport));
    }
    else if (CTC_FLAG_ISSET(p_rslt->flags, CTC_DIAG_PKT_LB_HASH_FLAGS_ECMP))
    {
        sys_nh_info_dsnh_t nhinfo;
        sal_memset(&nhinfo, 0, sizeof(nhinfo));
        CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, p_rslt->group_id, &nhinfo, 0));
        CTC_ERROR_RETURN(sys_usw_port_get_property(lchip, p_rslt->src_gport, CTC_PORT_PROP_LB_HASH_ECMP_PROFILE, &profile_id));
        if (profile_id)
        {
            lb_hash_offset.hash_module = CTC_LB_HASH_MODULE_ECMP;
            lb_hash_offset.hash_mode = CTC_LB_HASH_MODE_STATIC;
            lb_hash_offset.fwd_type = (1 == gen_lb_hash.is_vxlan)?CTC_LB_HASH_FWD_VXLAN:((1 == gen_lb_hash.is_nvgre)?CTC_LB_HASH_FWD_NVGRE:CTC_LB_HASH_FWD_IP);
            lb_hash_offset.profile_id = profile_id;
            lb_hash_offset.hecmp_grp_en = nhinfo.h_ecmp_en?1:0;
            CTC_ERROR_RETURN(sys_usw_global_ctl_get(lchip, CTC_GLOBAL_LB_HASH_OFFSET_PROFILE, &lb_hash_offset));
            profile_id = (lb_hash_offset.offset == CTC_LB_HASH_OFFSET_DISABLE)?0:profile_id;
            value = lb_hash_offset.offset;
        }

        if (0 == profile_id)
        {
            lb_hash_offset.hash_module = CTC_LB_HASH_MODULE_ECMP;
            lb_hash_offset.hash_mode = CTC_LB_HASH_MODE_STATIC;
            lb_hash_offset.fwd_type = (1 == gen_lb_hash.is_vxlan)?CTC_LB_HASH_FWD_VXLAN:((1 == gen_lb_hash.is_nvgre)?CTC_LB_HASH_FWD_NVGRE:CTC_LB_HASH_FWD_IP);
            lb_hash_offset.profile_id = CTC_LB_HASH_ECMP_GLOBAL_PROFILE;
            lb_hash_offset.hecmp_grp_en = nhinfo.h_ecmp_en?1:0;
            CTC_ERROR_RETURN(sys_usw_global_ctl_get(lchip, CTC_GLOBAL_LB_HASH_OFFSET_PROFILE, &lb_hash_offset));
            value = lb_hash_offset.offset;
        }
        hash_select = value/16;
        hash_offset = value%16;
        _sys_tsingma_diag_select_hash_value(hash_data, hash_select, hash_offset, DRV_IS_TSINGMA(lchip)?0:1, &hash_value);
        p_rslt->hash_val = hash_value;
        CTC_ERROR_RETURN(sys_usw_nh_ecmp_get_lb_hash_mem_api(lchip, p_rslt->group_id, hash_value, &p_rslt->dest_nhid));
    }

    return CTC_E_NONE;
}

#endif

